import { Directive } from "@vue/runtime-core";

const dialogDrag: Directive = {
  mounted(el: HTMLElement, binding): void {
    // 如果元素不允许拖动
    if (binding.value !== undefined && binding.value?.draggable === false) return
    /**
     * 拖拽元素头部元素
     */
    const eleHeader: HTMLElement = el.querySelector('#header')!;

    /**
     * body元素
     */
    const body: HTMLElement = document.body;

    (el as any).resize = (): void => {
      let bodyWid: number = body.scrollWidth;
      const bodyHei: number = body.scrollHeight;

      // 如果出现滚动条此时可能设置了body的padding-right来防止页面抖动
      const bodyPaddRight: number = +body.style.paddingRight.replace('px', '');
      if (bodyPaddRight) bodyWid -= bodyPaddRight;

      const rect: DOMRect = el.getBoundingClientRect();

      if (el.offsetWidth + rect.x + scrollX > bodyWid) {
        const left = bodyWid - el.offsetWidth - scrollX;
        el.style.left = `${left}px`
      }

      if (el.offsetHeight + rect.y + scrollY > bodyHei) {
        const left = bodyHei - el.offsetHeight - scrollY;
        el.style.top = `${left}px`
      }
    }
    window.addEventListener('resize', (el as any).resize)

    eleHeader.onmousedown = (e: MouseEvent): void => {
      // 移动前关闭需要关闭的框
      if (binding.value?.callback) binding.value.callback();
      /**
       * 鼠标点击处距离浏览器左边界的距离
       */
      const disX: number = e.clientX;
      /**
       * 鼠标点击处距离浏览器上边界的距离
       */
      const distY: number = e.clientY;
      const rect: DOMRect = el.getBoundingClientRect();
      /**
       * 拖拽元素距离浏览器上边界的距离
       */
      const dialogTop: number = rect.y + scrollY;
      /**
       * 拖拽元素距离浏览器左边界的距离
       */
      const dialogLeft: number = rect.x + scrollX;
      /**
       * 视图可视宽度
       */
      let bodyWid: number = body.scrollWidth;

      // 如果出现滚动条此时可能设置了body的padding-right来防止页面抖动
      const bodyPaddRight: number = +body.style.paddingRight.replace('px', '');
      if (bodyPaddRight) bodyWid -= bodyPaddRight;

      /**
       * 视图可视高度
       */
      const bodyHei: number = body.scrollHeight;
      /**
       * 拖拽元素宽度
       */
      const dialogWid: number = el.offsetWidth;
      /**
      * 拖拽元素高度
      */
      const dialogHei: number = el.offsetHeight;
      /**
       * 鼠标在水平方向最多可移动的距离
       */
      const maxX: number = bodyWid - dialogWid - dialogLeft;
      /**
       * 鼠标在竖直方向最多可移动的距离
       */
      const maxY: number = bodyHei - dialogHei - dialogTop;

      document.onmousemove = (e: MouseEvent): void => {
        /**
         * 鼠标水平移动的距离
         */
        let left: number = e.clientX - disX;
        /**
         * 鼠标竖直移动的距离
         */
        let top: number = e.clientY - distY;

        // 边界处理
        if (left > maxX) left = maxX;
        else if (-left > dialogLeft) left = -dialogLeft;

        if (top > maxY) top = maxY;
        else if (-top > dialogTop) top = -dialogTop;

        el.style.cssText += `
          position: absolute;
          left: ${dialogLeft + left}px;
          top: ${dialogTop + top}px;
          transform: translateX(0);
        `;
      }

      document.onmouseup = (): void => {
        if (document.onmousemove) document.onmousemove = null;
        document.onmouseup = null;
      }
    }
  },
  beforeUnmount(el): void {
    window.removeEventListener('resize', el.resize);
  },
}

export default dialogDrag